
package net.sf.odinms.server;

import java.awt.Point;
import java.awt.Rectangle;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import javax.script.ScriptException;

import net.sf.odinms.client.IItem;
import net.sf.odinms.client.ISkill;
import net.sf.odinms.client.MapleBuffStat;
import net.sf.odinms.client.MapleCharacter;
import net.sf.odinms.client.MapleDisease;
import net.sf.odinms.client.MapleInventory;
import net.sf.odinms.client.MapleInventoryType;
import net.sf.odinms.client.MapleJob;
import net.sf.odinms.client.MaplePet;
import net.sf.odinms.client.MapleStat;
import net.sf.odinms.client.SkillFactory;
import net.sf.odinms.client.status.MonsterStatus;
import net.sf.odinms.client.status.MonsterStatusEffect;
import net.sf.odinms.net.channel.ChannelServer;
import net.sf.odinms.provider.MapleData;
import net.sf.odinms.provider.MapleDataTool;
import net.sf.odinms.server.life.MapleMonster;
import net.sf.odinms.server.maps.MapleDoor;
import net.sf.odinms.server.maps.MapleMap;
import net.sf.odinms.server.maps.MapleMapObject;
import net.sf.odinms.server.maps.MapleMapObjectType;
import net.sf.odinms.server.maps.MapleMist;
import net.sf.odinms.server.maps.MapleSummon;
import net.sf.odinms.server.maps.SummonMovementType;
import net.sf.odinms.net.world.PlayerCoolDownValueHolder;
import net.sf.odinms.tools.ArrayMap;
import net.sf.odinms.tools.MaplePacketCreator;
import net.sf.odinms.tools.Pair;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import net.sf.odinms.client.skills.*;
import net.sf.odinms.server.maps.MapleDoor2;

/**
 * @author Matze
 * @author Frz
 */
public class MapleStatEffect implements Serializable {

    static final long serialVersionUID = 9179541993413738569L;
    private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MapleStatEffect.class);
    private static MapleStatEffect instance = null;
    private short watk,  matk,  wdef,  mdef,  acc,  avoid,  hands,  speed,  jump;
    private short hp,  mp;
    private double hpR,  mpR;
    private short mpCon,  hpCon;
    private int duration;
    private boolean overTime;
    private int sourceid;
    private int moveTo;
    private boolean skill;
    public List<Pair<MapleBuffStat, Integer>> statups;
    private Map<MonsterStatus, Integer> monsterStatus;
    private int x,  y,  z;
    private double prop;
    private int itemCon,  itemConNo;
    private int fixDamage;
    private int damage,  attackCount,  bulletCount,  bulletConsume;
    private Point lt,  rb;
    private int mobCount;
    private int moneyCon;
    private int cooldown;
    private boolean isMorph = false;
    private int morphId = 0;
    private List<MapleDisease> cureDebuffs;
    private int mastery,  range;
    private String remark;
    private int maxLevel;
    private int t;
    //private int damR;
    private boolean isGhost;
    /*
    private int fatigue;
    private int addMagic;
    private int decDamage;
    private int ignoreMobwdef;
    private int subDuration;
    private int terR;
    private int asrR;
    */
    private int epad;
    private int epdd;
    private int emdd;
    private int emhp;
    private int emmp;
    /*
    private int cr;
    private int criticaldamageMin;
    private int criticaldamageMax;
    private int dotDamage;
    private int dotInterval;
    private int dotTime;
    private int mesoR;
    private int u;
    private int v;
    private int w;
    private int pddR;
    private int expR;
    private int itemConsume;
    */
    private boolean firstDoor = true; //机械师
    private double mmpR, mhpR;
    
   public MapleStatEffect() {
        
    }
   
   public String getRemark() {
        return remark;
    }

   
   public static MapleStatEffect loadItemEffectFromData(MapleData source, int itemid) {
       return loadFromData(source, itemid, false, false);
    }
   
   private static void addBuffStatPairToListIfNotZero(List<Pair<MapleBuffStat, Integer>> list, MapleBuffStat buffstat, Integer val) {
        if (val.intValue() != 0) {
            list.add(new Pair<MapleBuffStat, Integer>(buffstat, val));
        }
    }
   
    //读取skill.xml， 貌似都是技能等级里面的
   public static MapleStatEffect loadSkillEffectFromData(MapleData source, int sourceid, int level, boolean beginner, boolean overTime) {
        MapleStatEffect ret = new MapleStatEffect();//定义角色效果ret
        if (level == 0 && beginner) {
            return loadFromData(source, sourceid, true, overTime);
        }
        ret.watk = (short)技能解析(MapleDataTool.getString("pad", source, null), level, 0);
        ret.matk = (short)技能解析(MapleDataTool.getString("mad", source, null), level, 0);
        ret.wdef = (short)技能解析(MapleDataTool.getString("pdd", source, null), level, 0);
        ret.mdef = (short)技能解析(MapleDataTool.getString("mdd", source, null), level, 0);
        ret.duration = 技能解析(MapleDataTool.getString("time", source, null), level, -1);
        ret.epad = 技能解析(MapleDataTool.getString("epad", source, null), level, 0);
        ret.epdd = 技能解析(MapleDataTool.getString("epdd", source, null), level, 0);
        ret.emdd = 技能解析(MapleDataTool.getString("emdd", source, null), level, 0);
        ret.acc = (short)技能解析(MapleDataTool.getString("acc", source, null), level, 0);
        ret.avoid = (short)技能解析(MapleDataTool.getString("eva", source, null), level, 0);
        ret.speed = (short)技能解析(MapleDataTool.getString("speed", source, null), level, 0);
        ret.jump = (short)技能解析(MapleDataTool.getString("jump", source, null), level, 0);
        ret.morphId = 技能解析(MapleDataTool.getString("morph", source, null), level, 0);
        ret.emhp = 技能解析(MapleDataTool.getString("emhp", source, null), level, 0);
        ret.emmp = 技能解析(MapleDataTool.getString("emmp", source, null), level, 0);
        ret.hp = (short)技能解析(MapleDataTool.getString("hp", source, null), level, 0);
        ret.mp = (short)技能解析(MapleDataTool.getString("mp", source, null), level, 0);
        ret.mpR = (技能解析(MapleDataTool.getString("mpR", source, null), level, 0) / 100.0);
        ret.hpR = (技能解析(MapleDataTool.getString("hpR", source, null), level, 0) / 100.0);
        ret.mpCon = (short)技能解析(MapleDataTool.getString("mpCon", source, null), level, 0);
        ret.hpCon = (short)技能解析(MapleDataTool.getString("hpCon", source, null), level, 0);
        ret.x = 技能解析(MapleDataTool.getString("x", source, null), level, 0);
        ret.y = 技能解析(MapleDataTool.getString("y", source, null), level, 0);
        ret.z = 技能解析(MapleDataTool.getString("z", source, null), level, 0);
        ret.damage = 技能解析(MapleDataTool.getString("damage", source, null), level, 100);
        int iprop = 技能解析(MapleDataTool.getString("prop", source, null), level, 100);
        ret.prop = iprop / 100.0;
        //技能提升Hp Mp上限
        ret.mhpR = (技能解析(MapleDataTool.getString("mhpR", source, null), level, 0) / 100.0);
        ret.mmpR = (技能解析(MapleDataTool.getString("mmpR", source, null), level, 0) / 100.0);
        //常用取值结束

        ret.range = 技能解析(MapleDataTool.getString("range", source, null), level, 0);
        ret.mobCount = 技能解析(MapleDataTool.getString("mobCount", source, null), level, 1);
        ret.mastery = 技能解析(MapleDataTool.getString("mastery", source, null), level, 0);
        ret.attackCount = 技能解析(MapleDataTool.getString("attackCount", source, null), level, 1);
        ret.mobCount = 技能解析(MapleDataTool.getString("mobCount", source, null), level, 1);
        ret.cooldown = 技能解析(MapleDataTool.getString("cooltime", source, null), level, 0);
        /*
         * 注释暂时用不到的取值 加快读取速度
        ret.pddR = 技能解析(MapleDataTool.getString("pddR", source, null), level, 0);
        ret.decDamage = 技能解析(MapleDataTool.getString("t", source, null), level, 0);
        ret.ignoreMobwdef = 技能解析(MapleDataTool.getString("ignoreMobpdpR", source, null), level, 0);
        ret.subDuration = 技能解析(MapleDataTool.getString("subTime", source, null), level, 0);
        ret.terR = 技能解析(MapleDataTool.getString("terR", source, null), level, 0);
        ret.asrR = 技能解析(MapleDataTool.getString("asrR", source, null), level, 0);
        ret.cr = 技能解析(MapleDataTool.getString("cr", source, null), level, 0);
        ret.dotDamage = 技能解析(MapleDataTool.getString("dot", source, null), level, 0);
        ret.dotInterval = 技能解析(MapleDataTool.getString("dotInterval", source, null), level, 0);
        ret.dotTime = 技能解析(MapleDataTool.getString("dotTime", source, null), level, 0);
        ret.addMagic = 技能解析(MapleDataTool.getString("madX", source, null), level, 0);
        ret.expR = 技能解析(MapleDataTool.getString("expR", source, null), level, 0);
        ret.damR = 技能解析(MapleDataTool.getString("damR", source, null), level, 0);
        ret.criticaldamageMax = 技能解析(MapleDataTool.getString("criticaldamageMax", source, null), level, 0);
        ret.criticaldamageMin = 技能解析(MapleDataTool.getString("criticaldamageMin", source, null), level, 0);
        ret.itemConsume = 技能解析(MapleDataTool.getString("itemConsume", source, null), level, 0);
        ret.mesoR = 技能解析(MapleDataTool.getString("mesoR", source, null), level, 0);
        ret.w = 技能解析(MapleDataTool.getString("w", source, null), level, 0);
        ret.u = 技能解析(MapleDataTool.getString("u", source, null), level, 0);
        ret.v = 技能解析(MapleDataTool.getString("v", source, null), level, 0);
        */
        ret.bulletCount = 技能解析(MapleDataTool.getString("bulletCount", source, null), level, 1);
        ret.itemCon = 技能解析(MapleDataTool.getString("itemCon", source, null), level, 0);
        ret.itemConNo = 技能解析(MapleDataTool.getString("itemConNo", source, null), level, 0);
        ret.moneyCon = 技能解析(MapleDataTool.getString("moneyCon", source, null), level, 0);
        ret.bulletConsume = 技能解析(MapleDataTool.getString("bulletConsume", source, null), level, 0);
        
        ArrayList statups = new ArrayList();
        if ((ret.overTime) && (ret.getSummonMovementType() == null)) {
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WATK, Integer.valueOf(ret.watk));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WDEF, Integer.valueOf(ret.wdef));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MATK, Integer.valueOf(ret.matk));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MDEF, Integer.valueOf(ret.mdef));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.ACC, Integer.valueOf(ret.acc));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.AVOID, Integer.valueOf(ret.avoid));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.SPEED, Integer.valueOf(ret.speed));
          addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
        }
        List cure = new ArrayList(5);
        if (MapleDataTool.getInt("poison", source, 0) > 0) {
          cure.add(MapleDisease.POISON);
        }
        if (MapleDataTool.getInt("seal", source, 0) > 0) {
          cure.add(MapleDisease.SEAL);
        }
        if (MapleDataTool.getInt("darkness", source, 0) > 0) {
          cure.add(MapleDisease.DARKNESS);
        }
        if (MapleDataTool.getInt("weakness", source, 0) > 0) {
          cure.add(MapleDisease.WEAKEN);
        }
        if (MapleDataTool.getInt("curse", source, 0) > 0) {
          cure.add(MapleDisease.CURSE);
        }
        ret.cureDebuffs = cure;
        MapleData ltd = source.getChildByPath("lt");
        if (ltd != null) {
            ret.lt = ((Point)ltd.getData());
            ret.rb = ((Point)source.getChildByPath("rb").getData());
        }
        ret.sourceid = sourceid;
        ret.skill = true;
        if (!ret.skill && ret.duration > -1) {
            ret.overTime = true;
        } else {
            ret.duration *= 1000;
            ret.overTime = overTime;
        }
        ret.moveTo = MapleDataTool.getInt("moveTo", source, -1);
        Map monsterStatus = new ArrayMap();
        //Map<MonsterStatus, Integer> monsterStatus = new ArrayMap<MonsterStatus, Integer>();
        if (ret.skill) { // hack because we can't get from the datafile...无法从数据文件获取的技能列表
            switch (sourceid) {
                case 法师.魔法盾: // 魔法盾
                case 炎术士.魔法盾://魔法盾
                case 龙神.魔法盾://魔法盾
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MAGIC_GUARD, Integer.valueOf(ret.x)));
                    break;
                case 牧师.神之保护: // 神之保护
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.INVINCIBLE, Integer.valueOf(ret.x)));
                    break;
                case 管理员.隐藏术: // 隐藏术
                    ret.duration = 60 * 120 * 1000;
                    ret.overTime = true;
                case 飞侠.隐身术: // 隐身术
                case 夜行者.隐身术:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DARKSIGHT, Integer.valueOf(ret.x)));
                    break;
                case 刀飞.敛财术: // 敛财术
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.PICKPOCKET, Integer.valueOf(ret.x)));
                    break;
                case 刀飞.金钱护盾: // 金钱护盾
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MESOGUARD, Integer.valueOf(ret.x)));
                    break;
                case 标飞.聚财术: // 聚财术
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MESOUP, Integer.valueOf(ret.x)));
                    break;
                case 标飞.影分身: //影分身
                case 夜行者.影分身://影分身
                case 双刀.镜像分身: //镜像分身
                case 刀飞.影分身: //刀飞的影分身
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SHADOWPARTNER, Integer.valueOf(ret.x)));
                    break;
                case 弓手.无形箭: // 无形箭
                case 弩手.无形箭: //无形箭
                case 牧师.时空门: // 时空门
                case 风灵使者.无形箭: //精灵使者-无形箭
                case 弩骑.无形箭_弩: //弩骑 无形箭：弩
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SOULARROW, Integer.valueOf(ret.x)));
                    break;
                case 骑士.火焰冲击: //火焰冲击
                case 骑士.寒冰冲击: // 寒冰冲击
                case 骑士.雷鸣冲击: //雷鸣冲击
                case 骑士.神圣冲击: //神圣冲击
                case 奇袭者.雷鸣: //雷鸣
                case 战神.冰雪矛: //冰雪矛
                case 魂骑士.灵魂属性:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WK_CHARGE, Integer.valueOf(ret.x)));
                    break;
                case 勇士.快速武器: // 剑客 - 快速武器
                case 骑士.快速武器: // 准骑士 - 快速武器
                case 龙骑.快速武器: // 枪战士 - 快速武器
                case 火毒.魔法狂暴: // 火毒巫师 - 魔法狂暴
                case 冰雷.魔法狂暴: // 冰雷巫师 - 魔法狂暴
                case 弓手.快速箭: // 猎人 - 快速箭
                case 弩手.快速弩: // 弩弓手 - 快速弩
                case 标飞.快速暗器: // 刺客 - 快速暗器
                case 刀飞.快速短刀: // 侠客 - 快速短刀
                case 双刀.快速双刀: // 刀客 - 快速双刀
                case 拳手.急速拳: // 拳手 - 急速拳
                case 枪手.速射: // 火枪手 - 速射
                case 魂骑士.快速剑: // 魂骑士 - 快速剑
                case 炎术士.魔法狂暴: // 炎术士 - 魔法狂暴
                case 风灵使者.快速箭: // 风灵使者 - 快速箭
                case 夜行者.快速暗器: // 夜行者 - 快速暗器
                case 奇袭者.急速拳: // 奇袭者 - 急速拳
                case 战神.快速矛: // 战神 - 快速矛
                case 龙神.魔法狂暴: // 龙神 - 魔法狂暴
                case 战法.快速长杖: // 幻灵斗师 - 快速长杖
                case 弩骑.快速弩: // 豹弩游侠 - 快速弩
                case 机械师.机械加速: // 机械师 - 机械加速
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.BOOSTER, Integer.valueOf(ret.x)));
                    break;
                case 拳手.极速领域:// 拳手 - 极速领域
                case 奇袭者.极速领域: //奇袭者 - 极速领域
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.极速领域, Integer.valueOf(ret.x)));
                    break;
                case 勇士.愤怒之火: // 愤怒之火
                case 魂骑士.愤怒之火: // 愤怒之火
                    //以上2个技能093取消防御减少
                case 勇士.葵花宝典: // 葵花宝典
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WATK, Integer.valueOf(ret.watk)));
                    break;
                case 龙骑.极限防御: //龙骑 - 极限防御
                case 法师.魔法铠甲: //法师 - 魔法铠甲
                case 炎术士.魔法铠甲://龙神 - 魔法铠甲
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WDEF, Integer.valueOf(ret.wdef)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MDEF, Integer.valueOf(ret.mdef)));
                    break;
                case 战士.圣甲术: //战士 - 圣甲术
                case 魂骑士.圣甲术://魂骑士 - 圣甲术
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WDEF, Integer.valueOf(ret.wdef)));
                    break;
                case 火毒.精神力: // 精神力
                case 2201001: // 精神力
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MATK, Integer.valueOf(ret.matk)));
                    break;
                case 标飞.轻功: // 轻功
                case 刀飞.轻功: // 轻功
                case 管理员.上乘轻功: // gm 轻功
                case 双刀.暗影轻功: //暗影轻功
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.speed)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.JUMP, Integer.valueOf(ret.jump)));
                    break;
                case 牧师.祝福: // 祝福
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.祝福, Integer.valueOf(level)));
                    break;
                case 弓箭手.集中术: // 集中术
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.ACC, Integer.valueOf(ret.acc)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.AVOID, Integer.valueOf(ret.avoid)));
                    break;
                case 管理员.枫印祝福: // gm 枫印祝福
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MATK, Integer.valueOf(ret.matk)));
                case 弓手.集中精力: // 集中精力
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WATK, Integer.valueOf(ret.watk)));
                    break;
                case 海盗.疾驰: // 疾驰
                case 双刀.龙卷风: // 龙卷风
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.疾驰_龙卷风, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.疾驰_龙卷风, Integer.valueOf(ret.y)));
                    break;
                case 勇士.伤害反击: // 伤害反击
                case 骑士.伤害反击:// 伤害反击
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.POWERGUARD, Integer.valueOf(ret.x)));
                    break;
                case 龙骑.神圣之火://神圣之火
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HYPERBODYHP, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HYPERBODYMP, Integer.valueOf(ret.y)));
                    break;
                case 勇士.斗气集中: // 斗气集中
                case 魂骑士.斗气集中:// 斗气集中
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.COMBO, Integer.valueOf(1)));
                    break;
                case 新手.狂暴战魂://勇士的意志
                case 战神.狂暴战魂://勇士的意志
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.BERSERK_FURY, Integer.valueOf(1)));
                    break;
                case 新手.骑兽技能: // 骑兽技能
                case 初心者.骑兽技能:// 骑兽技能
                case 战神.骑兽技能:// 骑兽技能
                case 枪手.武装: // 骑兽技能
                case 龙神.骑兽技能:// 骑兽技能
                case 弩骑.美洲豹骑士://美洲豹骑士
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.骑宠1, Integer.valueOf(0)));
                    break;
                case 龙骑.龙咆哮: //龙咆哮
                case 战神.斗气重生:
                    ret.hpR = -ret.x / 100.0;
                    break;
                case 龙骑.龙之魂: // 龙之魂
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WATK, Integer.valueOf(ret.watk)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DRAGONBLOOD, Integer.valueOf(ret.x)));
                    break;
                case 勇士.冒险岛勇士: // 冒险岛勇士
                case 骑士.冒险岛勇士: // 冒险岛勇士
                case 龙骑.冒险岛勇士: // 冒险岛勇士
                case 火毒.冒险岛勇士: // 冒险岛勇士
                case 冰雷.冒险岛勇士: // 冒险岛勇士
                case 牧师.冒险岛勇士: // 冒险岛勇士
                case 弓手.冒险岛勇士: // 冒险岛勇士
                case 弩手.冒险岛勇士: // 冒险岛勇士
                case 标飞.冒险岛勇士: // 冒险岛勇士
                case 刀飞.冒险岛勇士: // 冒险岛勇士
                case 双刀.冒险岛勇士: // 冒险岛勇士
                case 拳手.冒险岛勇士: // 冒险岛勇士
                case 枪手.冒险岛勇士: // 冒险岛勇士
                case 战神.冒险岛勇士: // 冒险岛勇士
                case 龙神.冒险岛勇士:
                case 弩骑.冒险岛勇士: //弩骑勇士
                case 机械师.冒险岛勇士: //机械勇士
                case 战法.冒险岛勇士: //幻灵勇士
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MAPLE_WARRIOR, Integer.valueOf(ret.x)));
                    break;
                case 弓手.火眼晶晶: // 火眼晶晶
                case 弩手.火眼晶晶: // 火眼晶晶
                case 弩骑.火眼晶晶:// 弩骑火眼
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SHARP_EYES, Integer.valueOf(ret.x << 8 | ret.y)));
                    break;
                case 龙骑.灵魂助力: //灵魂助力
                case 冰雷.冰破魔兽: //冰雷 - 冰破魔兽
                case 牧师.圣龙召唤: //圣龙召唤
                case 牧师.强化圣龙: // 强化圣龙
                case 弓手.火凤凰: // 火凤凰
                case 枪手.章鱼炮台: //章鱼炮台
                case 枪手.海鸥空袭: //海鸥空袭
                case 枪手.超级章鱼炮台: // 超级章鱼炮台
                case 魂骑士.魂精灵://魂精灵
                case 炎术士.炎精灵://炎精灵
                case 风灵使者.风精灵://风精灵
                case 夜行者.夜精灵://夜精灵
                case 奇袭者.雷精灵://雷精灵
                case 炎术士.火魔兽://火魔兽
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SUMMON, Integer.valueOf(1)));
                    break;
                case 牧师.神圣祈祷: // 神圣祈祷
                case 管理员.神圣祈祷: // GM 神圣祈祷
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HOLY_SYMBOL, Integer.valueOf(ret.x)));
                    break;
                case 标飞.暗器伤人: // 暗器伤人
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SHADOW_CLAW, Integer.valueOf(0)));
                    break;
                case 火毒.终极无限:// 终极无限
                case 冰雷.终极无限:// 终极无限
                case 牧师.终极无限: // 终极无限
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.INFINITY, Integer.valueOf(ret.x)));
                    break;
                case 勇士.稳如泰山: // 稳如泰山
                case 骑士.稳如泰山: // 稳如泰山
                case 龙骑.稳如泰山: // 稳如泰山
                case 战神.战神的意志: //战神的意志
                case 战法.稳如泰山: //战法 稳如泰山
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.STANCE, Integer.valueOf(ret.x))); //ret.x定值为1
                    break;
                case 新手.英雄之回声: // 英雄之回声
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.ECHO_OF_HERO, Integer.valueOf(ret.x)));
                    break;
                case 火毒.魔法反击: // 魔法反击
                case 冰雷.魔法反击: // 魔法反击
                case 牧师.魔法反击: // 魔法反击
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MANA_REFLECTION, Integer.valueOf(1)));
                    break;
                case 牧师.圣灵之盾: // 圣灵之盾
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HOLY_SHIELD, Integer.valueOf(ret.x)));
                    break;
                case 弓手.替身术: // 射手 - 替身术
                case 弩手.替身术: // 游侠 - 替身术
                case 双刀.傀儡召唤: // 暗影双刀 - 傀儡召唤
                case 风灵使者.替身术: //风灵使者 - 替身术
                    /*
                case 35111002: // 机械师 - 磁场
                case 35111005: // 机械师 - 加速器：EX-7
                case 35111011: // 机械师 - 治疗机器人：H-LX
                case 35121003: // 机械师 - 战争机器：泰坦
                case 35121010: // 机械师 - 放大器：AF-11
                    */
                case 弩骑.野性陷阱: //野性陷阱
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.PUPPET, Integer.valueOf(1)));
                    break;
                    
                case 火毒.快速移动精通: //快速移动精通 开关技能
                case 冰雷.快速移动精通:
                case 牧师.快速移动精通:
                case 战法.快速移动精通:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.快速移动精通, Integer.valueOf(ret.x)));
                    ret.duration = 9999999;
                    break;
                case 战法.飓风: //飓风
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.飓风, Integer.valueOf(1)));
                    break;
                case 战法.转化: //转化
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.转化, Integer.valueOf(ret.x)));
                    break;
                case 战法.黑暗灵气: //黑暗灵气
                case 战法.蓝色灵气: //蓝色灵气
                case 战法.黄色灵气: //黄色灵气
                case 战法.进阶黑暗灵气:
                case 战法.进阶蓝色灵气:
                case 战法.进阶黄色灵气:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.灵气, Integer.valueOf(ret.x)));
                    ret.duration = 9999999;
                    break;
                case 战神.灵巧击退: //灵巧击退
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.灵巧击退, Integer.valueOf(ret.x)));
                    break;
                case 战法.伤害吸收: //伤害吸收
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.伤害吸收, Integer.valueOf(ret.x)));
                    break;
                case 战神.抗压: //抗压
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.抗压, Integer.valueOf(ret.x)));
                    break;
                case 龙神.魔法屏障: //魔法屏障
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.魔法屏障, Integer.valueOf(ret.x)));
                    break;
                case 双刀.荆棘: //荆棘 093更改 变为2个buff叠加 原有buff取消
                    //statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.荆棘, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.EWatk, Integer.valueOf(ret.epad)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.STANCE, Integer.valueOf(ret.x)));
                    break;
                case 龙神.缓速术: //缓速术
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.缓速术, Integer.valueOf(ret.x)));
                    break;
                case 战法.霸体: //霸体
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.霸体, Integer.valueOf(ret.x)));
                    break;
                case 机械师.火焰喷射器:
                case 机械师.强化火焰喷射器:
                case 机械师.金属机甲_导弹战车:
                    ret.duration = 2100000000;
                case 机械师.金属机甲_重机枪:
                case 机械师.金属机甲_重机枪_4转:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.机械师, Integer.valueOf(level)));
                    break;
                case 战神.连环吸血: //连环吸血
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.连环吸血, Integer.valueOf(ret.x)));
                    break;
                case 战法.重生: //重生
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.重生, Integer.valueOf(ret.x)));
                    break;
                case 弩骑.暴走形态: //暴走状态
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.暴走HP, Integer.valueOf(ret.x)));
                    //这个决定是否出现翅膀
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.暴走攻击, Integer.valueOf(ret.y)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.z)));
                    break;
                case 弩手.刺眼箭: // 刺眼箭
                case 弩骑.致盲:// 弩骑 致盲
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.BLIND, Integer.valueOf(ret.x)));
                    break;
                case 弓手.缓速箭: // 缓速箭
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HAMSTRING, Integer.valueOf(ret.x)));
                    break;
                    /*
                case 33101006: // 吞噬 消化技能
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.吞噬1, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.吞噬2, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.吞噬3, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.吞噬4, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.吞噬5, Integer.valueOf(ret.x)));
                    break;
                    */
                case 弩骑.地雷: //地雷
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.地雷, Integer.valueOf(ret.x)));
                    break;
                case 拳手.超人变形: //超人变形
                case 拳手.超级变身: //超级变身
                case 风灵使者.信天翁://风灵使者 - 信天翁
                case 奇袭者.超人变形://奇袭者 - 超级变身
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.EWatk, Integer.valueOf(ret.epad)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.EWdef, Integer.valueOf(ret.epdd)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.EMdef, Integer.valueOf(ret.emdd)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.speed)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.JUMP, Integer.valueOf(ret.jump)));
                    //根据封包发送顺序 这个值要放在最后发送
                    //statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MORPH, Integer.valueOf(ret.morphId)));
                    //2002是冰骑士 换着玩
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MORPH, Integer.valueOf(ret.morphId)));
                    break;
                case 双刀.终极斩: //终极斩
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.终极斩, Integer.valueOf(ret.y)));
                    break;
                case 双刀.死亡猫头鹰: //死亡猫头鹰 奖励次数 5+u(x/4) 次
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.死亡猫头鹰, Integer.valueOf(ret.y)));
                    ret.duration = 2100000000;
                    break;
                case 战神.战神之盾: //战神之盾
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.战神之盾, Integer.valueOf(ret.x)));
                    break;
                case 战神.矛连击强化: //矛连击强化
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.矛连击强化, Integer.valueOf(level * 10)));
                    ret.duration = 2100000000;
                    break;
                case 龙神.灵魂之石: //灵魂之石
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.灵魂之石, Integer.valueOf(ret.x)));
                    break;
                case 龙神.抗魔领域: //抗魔领域
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.抗魔领域, Integer.valueOf(ret.x)));
                    break;
                case 龙神.玛瑙的祝福: //玛瑙的祝福
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WDEF, Integer.valueOf(ret.wdef)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MDEF, Integer.valueOf(ret.mdef)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MATK, Integer.valueOf(ret.matk)));
                    break;
                case 骑士.战斗命令: //战斗命令
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.战斗命令, Integer.valueOf(ret.x)));
                    break;
                case 骑士.祝福护甲: //祝福护甲
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.祝福护甲, Integer.valueOf(ret.x))); //防御次数
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.祝福护甲, Integer.valueOf(ret.watk))); //增加的攻击力
                    break;
                case 拳手.能量获得: //能量获得
                case 奇袭者.能量获得:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.能量获得, Integer.valueOf(10000))); //满能量时才能发动
                    break;
                case 冰雷.自然力重置: //自然力重置
                case 火毒.自然力重置:
                case 炎术士.自然力重置:
                case 龙神.自然力重置:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.自然力重置, Integer.valueOf(ret.x)));
                    break;
                case 风灵使者.风影漫步: //风影漫步
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.speed)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.风影漫步, Integer.valueOf(1))); //也可以写ret.x 不过x节点定值为1
                    break;
                case 机械师.完美机甲:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.完美机甲, Integer.valueOf(ret.x)));
                    ret.duration = 2100000000;
                    break;
                case 机械师.卫星防护:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.卫星防护, Integer.valueOf(ret.x)));
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.完美机甲, Integer.valueOf(ret.y)));
                    ret.duration = 2100000000;
                    break;
                case 风灵使者.终极弓: //骑士团的终极技能比较特殊 是Buff
                case 魂骑士.终极剑:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.骑士团主动终极, Integer.valueOf(1))); //也可以写ret.x 不过x节点定值为1
                    break;
                case 枪手.幸运骰子:
                case 拳手.幸运骰子:
                case 机械师.幸运骰子:
                    //这里固定1点数 具体还要去下面处理随机点数
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.幸运骰子, Integer.valueOf(1)));
                    break;
                case 奇袭者.闪光击:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.闪光击, Integer.valueOf(1))); //也可以写ret.x 不过x节点定值为1
                    break;
                case 龙神.玛瑙的保佑:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.玛瑙的保佑, Integer.valueOf(ret.x)));
                    break;
                case 龙神.玛瑙的意志:
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.玛瑙的意志, Integer.valueOf(ret.x)));
                    break;
                    
                    //给予怪物状态
                case 战神.战神之审判:
                    monsterStatus.put(MonsterStatus.FREEZE, Integer.valueOf(1));
                    monsterStatus.put(MonsterStatus.POISON, Integer.valueOf(ret.damage));
                    break;
                    
                case 机械师.加速器: 
                    monsterStatus.put(MonsterStatus.WDEF, Integer.valueOf(ret.y));
                    monsterStatus.put(MonsterStatus.SPEED, Integer.valueOf(ret.x));
                    break;
                case 勇士.魔击无效: //魔击无效
                case 骑士.魔击无效:
                case 龙骑.魔击无效:
                    //定值
                    monsterStatus.put(MonsterStatus.魔击无效, Integer.valueOf(1));
                    break;
                case 龙神.鬼刻符: //鬼刻符
                    monsterStatus.put(MonsterStatus.鬼刻符, Integer.valueOf(ret.x));
                    break;
                case 双刀.怪物炸弹: //怪物炸弹
                    monsterStatus.put(MonsterStatus.怪物炸弹, Integer.valueOf(ret.damage));
                    break;
                case 飞侠.诅咒术: // 诅咒术
                    monsterStatus.put(MonsterStatus.WATK, Integer.valueOf(ret.x));
                    monsterStatus.put(MonsterStatus.WDEF, Integer.valueOf(ret.y));
                    break;
                case 骑士.压制术: // 压制术
                    monsterStatus.put(MonsterStatus.WATK, Integer.valueOf(ret.x));
                    monsterStatus.put(MonsterStatus.WDEF, Integer.valueOf(ret.y));
                    break;
                case 骑士.属性攻击: // 属性攻击
                case 勇士.虎咆哮: // 虎咆哮
                case 刀飞.落叶斩: // 落叶斩
                case 弓手.爆炸箭: // 爆炸箭
                case 勇士.昏迷: // 昏迷
                case 魂骑士.灵魂突刺: // 灵魂突刺
                case 刀飞.一出双击: // 一出双击
                case 拳手.回马: // 回马
                case 拳手.升龙连击: // 升龙连击
                case 拳手.金手指: // 金手指
                case 拳手.索命: // 索命
                case 拳手.光速拳: // 光速拳
                case 枪手.迷惑射击: // 迷惑射击
                case 魂骑士.昏迷: //昏迷
                case 龙神.火焰喷射: // 龙神 - 火焰喷射
                case 弩骑.炸裂箭: //炸裂箭 
                case 弩骑.美洲豹怒吼: //美洲豹怒吼
                case 弩骑.十字攻击: //十字攻击
                case 弩骑.音速震波: //音速震波
                case 机械师.磁场:
                case 龙神.魔力闪爆:
                    monsterStatus.put(MonsterStatus.STUN, Integer.valueOf(1));
                    break;
                    
                case 标飞.挑衅://挑衅
                case 刀飞.挑衅://挑衅
                    monsterStatus.put(MonsterStatus.TAUNT, Integer.valueOf(ret.x));
                    monsterStatus.put(MonsterStatus.MDEF, Integer.valueOf(ret.x));
                    monsterStatus.put(MonsterStatus.WDEF, Integer.valueOf(ret.x));
                    break;
                case 标飞.忍者伏击: // 忍者伏击
                case 刀飞.忍者伏击: // 忍者伏击
                    monsterStatus.put(MonsterStatus.忍者伏击, Integer.valueOf(ret.damage));
                    break;
                case 冰雷.冰冻术: // 冰冻术
                case 冰雷.冰咆哮: // 冰咆哮
                case 弩手.寒冰箭: // 寒冰箭
                case 冰雷.冰雷合击: // 冰雷合击
                case 冰雷.落霜冰破: // 落霜冰破
                case 枪手.寒冰喷射: // 寒冰喷射
                case 火毒.美杜莎之眼: // 美杜莎之眼
                case 战神.钻石星辰:
                    monsterStatus.put(MonsterStatus.FREEZE, Integer.valueOf(1)); //赋予冰冻属性
                    ret.duration *= 2; // freezing skills are a little strange
                    break;
                case 火毒.火凤球: // 火凤球
                case 冰雷.冰凤球: // 冰凤球
                    monsterStatus.put(MonsterStatus.POISON, Integer.valueOf(1));
                    monsterStatus.put(MonsterStatus.FREEZE, Integer.valueOf(1));
                    break;
                case 火毒.缓速术: // 缓速术
                case 冰雷.缓速术: // 缓速术
                    monsterStatus.put(MonsterStatus.SPEED, Integer.valueOf(ret.x));
                    break;
                case 火毒.毒雾术: // 毒雾术
                    ret.duration = (int) (5 + Math.floor(level / 4) );
                case 火毒.火毒合击: // 火毒 - 火毒合击
                    monsterStatus.put(MonsterStatus.POISON, Integer.valueOf(1));
                    break;
                case 牧师.巫毒术: //巫毒术
                    monsterStatus.put(MonsterStatus.DOOM, Integer.valueOf(1));
                    break;
                case 弓手.银鹰召唤: // 银鹰召唤
                case 弩手.金鹰召唤: // 金鹰召唤
                case 弩骑.银鹰: // 银鹰召唤
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SUMMON, Integer.valueOf(1)));
                    monsterStatus.put(MonsterStatus.STUN, Integer.valueOf(1));
                    break;
                case 火毒.火魔兽: // 火魔兽
                case 弩手.冰凤凰: //冰凤凰
                    statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SUMMON, Integer.valueOf(1)));
                    monsterStatus.put(MonsterStatus.FREEZE, Integer.valueOf(1));
                    break;
                case 火毒.封印术: //封印术
                case 冰雷.封印术: //封印术
                case 炎术士.封印术://封印术
                    monsterStatus.put(MonsterStatus.SEAL, 1);
                    break;
                case 标飞.影网术: // 影网术
                case 夜行者.影网术://影网术
                    monsterStatus.put(MonsterStatus.SHADOW_WEB, 1);
                    break;
                case 枪手.心灵控制://心灵控制
                    monsterStatus.put(MonsterStatus.HYPNOTIZED, 1);
                    break;
                default:
                    break;
            }
        }
        if (ret.isMorph() && !ret.isPirateMorph()) {
            statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MORPH, Integer.valueOf(ret.getMorph())));
        }
        ret.monsterStatus = monsterStatus;
        statups.trimToSize();
        ret.statups = statups;
        return ret;
    }
   
   private static MapleStatEffect loadFromData(MapleData source, int sourceid, boolean skill, boolean overTime) {
     MapleStatEffect ret = new MapleStatEffect();
     ret.duration = MapleDataTool.getIntConvert("time", source, -1);
     ret.hp = (short)MapleDataTool.getInt("hp", source, 0);
     ret.hpR = (MapleDataTool.getInt("hpR", source, 0) / 100.0D);
     ret.mp = (short)MapleDataTool.getInt("mp", source, 0);
     ret.mpR = (MapleDataTool.getInt("mpR", source, 0) / 100.0D);
     ret.mpCon = (short)MapleDataTool.getInt("mpCon", source, 0);
     ret.hpCon = (short)MapleDataTool.getInt("hpCon", source, 0);
     int iprop = MapleDataTool.getInt("prop", source, 100);
     ret.prop = (iprop / 100.0D);
     ret.mobCount = MapleDataTool.getInt("mobCount", source, 1);
     ret.cooldown = MapleDataTool.getInt("cooltime", source, 0);
     ret.morphId = MapleDataTool.getInt("morph", source, 0);
     ret.isGhost = (MapleDataTool.getInt("ghost", source, 0) != 0);
     //ret.fatigue = MapleDataTool.getInt("incFatigue", source, 0);
     ret.sourceid = sourceid;
     ret.skill = skill;
     if ((!ret.skill) && (ret.duration > -1)) {
       ret.overTime = true;
     } else {
       ret.duration *= 1000;
       ret.overTime = overTime;
     }
     ArrayList statups = new ArrayList();
     ret.watk = (short)MapleDataTool.getInt("pad", source, 0);
     ret.wdef = (short)MapleDataTool.getInt("pdd", source, 0);
     ret.matk = (short)MapleDataTool.getInt("mad", source, 0);
     ret.mdef = (short)MapleDataTool.getInt("mdd", source, 0);
     ret.acc = (short)MapleDataTool.getIntConvert("acc", source, 0);
     ret.avoid = (short)MapleDataTool.getInt("eva", source, 0);
     ret.speed = (short)MapleDataTool.getInt("speed", source, 0);
     ret.jump = (short)MapleDataTool.getInt("jump", source, 0);
     List cure = new ArrayList(5);
     if (MapleDataTool.getInt("poison", source, 0) > 0)
       cure.add(MapleDisease.POISON);
     if (MapleDataTool.getInt("seal", source, 0) > 0) 
       cure.add(MapleDisease.SEAL);
     if (MapleDataTool.getInt("darkness", source, 0) > 0) 
       cure.add(MapleDisease.DARKNESS);
     if (MapleDataTool.getInt("weakness", source, 0) > 0) 
       cure.add(MapleDisease.WEAKEN);
     if (MapleDataTool.getInt("curse", source, 0) > 0) 
       cure.add(MapleDisease.CURSE);
     ret.cureDebuffs = cure;
     if ((ret.overTime) && (ret.getSummonMovementType() == null)) {
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WATK, Integer.valueOf(ret.watk));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WDEF, Integer.valueOf(ret.wdef));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MATK, Integer.valueOf(ret.matk));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MDEF, Integer.valueOf(ret.mdef));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.ACC, Integer.valueOf(ret.acc));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.AVOID, Integer.valueOf(ret.avoid));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.SPEED, Integer.valueOf(ret.speed));
       addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
     }
     MapleData ltd = source.getChildByPath("lt");
     if (ltd != null) {
       ret.lt = ((Point)ltd.getData());
       ret.rb = ((Point)source.getChildByPath("rb").getData());
     }
     int x = MapleDataTool.getInt("x", source, 0);
     ret.x = x;
     ret.y = MapleDataTool.getInt("y", source, 0);
     ret.damage = MapleDataTool.getIntConvert("damage", source, 100);
     ret.attackCount = MapleDataTool.getIntConvert("attackCount", source, 1);
     ret.bulletCount = MapleDataTool.getIntConvert("bulletCount", source, 1);
     ret.bulletConsume = MapleDataTool.getIntConvert("bulletConsume", source, 0);
     ret.moneyCon = MapleDataTool.getIntConvert("moneyCon", source, 0);
     ret.itemCon = MapleDataTool.getInt("itemCon", source, 0);
     ret.itemConNo = MapleDataTool.getInt("itemConNo", source, 0);
     ret.moveTo = MapleDataTool.getInt("moveTo", source, -1);
     Map monsterStatus = new ArrayMap();
     if (skill) {
       switch (sourceid) {
           case 管理员.神圣之火://gm神圣之火
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HYPERBODYHP, Integer.valueOf(ret.x)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HYPERBODYMP, Integer.valueOf(ret.y)));
               break;
           case 新手.团队治疗: // 新手 - 团队治疗
           case 初心者.团队治疗:
           case 战神.团队治疗:
           case 龙神.团队治疗:
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.RECOVERY, Integer.valueOf(ret.x)));
               break;
           case 新手.疾风步: // 新手 - 疾风步
           case 初心者.疾风步:
           case 战神.疾风步:
           case 龙神.疾风步:
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.x)));
               break;
           case 新手.骑兽技能: // 新手 - 骑兽技能
           case 初心者.骑兽技能:
           case 战神.骑兽技能:
           case 龙神.骑兽技能:
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.骑宠1, Integer.valueOf(1)));
               break;
           case 新手.英雄之回声: // 新手 - 英雄之回声
           case 初心者.英雄之回声:
           case 战神.英雄之回声:
           case 龙神.英雄之回声:
           case 预备兵.英雄之回声:
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.ECHO_OF_HERO, Integer.valueOf(ret.x)));
               break;
           case 新手.金刚霸体: // 新手 - 金刚霸体
           case 初心者.金刚霸体:
           case 战神.金刚霸体:
           case 龙神.金刚霸体:
               //statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DIVINE_BODY, 1));
               break;
           case 新手.狂暴战魂: // 新手 - 狂暴战魂
           case 初心者.狂暴战魂:
           case 战神.狂暴战魂:
           case 龙神.狂暴战魂:
           //case 预备兵.狂暴战魂:
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.BERSERK_FURY, Integer.valueOf(1)));
               break;
           case 管理员.上乘轻功: // 管理员 - 上乘轻功
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.speed)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.JUMP, Integer.valueOf(ret.jump)));
               break;
           case 管理员.神圣祈祷: // 管理员 - 神圣祈祷
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.HOLY_SYMBOL, Integer.valueOf(ret.x)));
               break;
           case 管理员.枫印祝福: // 管理员 - 枫印祝福
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.ACC, Integer.valueOf(ret.acc)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.AVOID, Integer.valueOf(ret.avoid)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WATK, Integer.valueOf(ret.watk)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MATK, Integer.valueOf(ret.matk)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.WDEF, Integer.valueOf(ret.wdef)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MDEF, Integer.valueOf(ret.mdef)));
               break;
           case 管理员.隐藏术: // 管理员 - 隐藏术
               ret.duration = 7200000;
               ret.overTime = true;
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DARKSIGHT, Integer.valueOf(ret.x)));
               break;
               //潜入
           case 预备兵.潜入:
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.潜入, Integer.valueOf(ret.x)));
               statups.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(ret.speed)));
               break;
       }
     }

     if (ret.isMorph()) {
       statups.add(new Pair(MapleBuffStat.MORPH, Integer.valueOf(ret.getMorph())));
     }
     if ((ret.isGhost) && (!skill)) {
       statups.add(new Pair(MapleBuffStat.GHOST_MORPH, Integer.valueOf(1)));
     }
     ret.monsterStatus = monsterStatus;
     statups.trimToSize();
     ret.statups = statups;
     return ret;
   }
   
    /**
     * @param applyto
     * @param obj
     * @param attack damage done by the skill
     */
    public void applyPassive(MapleCharacter applyto, MapleMapObject obj, int attack) {
        if (makeChanceResult()) {
            switch (sourceid) {
                // MP eater
                case 火毒.魔力吸收:
                case 冰雷.魔力吸收:
                case 牧师.魔力吸收:
                    if (obj == null || obj.getType() != MapleMapObjectType.MONSTER) {
                        return;
                    }
                    MapleMonster mob = (MapleMonster) obj;
                    // x is absorb percentage
                    if (!mob.isBoss()) {
                        int absorbMp = Math.min((int) (mob.getMaxMp() * (getX() / 100.0)), mob.getMp());
                        if (absorbMp > 0) {
                            mob.setMp(mob.getMp() - absorbMp);
                            applyto.addMP(absorbMp);
                            applyto.getClient().getSession().write(MaplePacketCreator.showOwnBuffEffect(sourceid, 1));
                            applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.showBuffeffect(applyto.getId(), sourceid, 1, (byte) 3), false);
                        }
                    }
                    break;
            }
        }
    }

    public boolean applyTo(MapleCharacter chr) {
        return applyTo(chr, chr, true, null);
    }

    public boolean applyTo(MapleCharacter chr, Point pos) {
        return applyTo(chr, chr, true, pos);
    }

    private boolean applyTo(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary, Point pos) {
        int hpchange = calcHPChange(applyfrom, primary);
        int mpchange = calcMPChange(applyfrom, primary);

        if (primary) {
            if (itemConNo != 0) {
                MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(itemCon);
                MapleInventoryManipulator.removeById(applyto.getClient(), type, itemCon, itemConNo, false, true);
            }
        }
        if (cureDebuffs.size() > 0) {
            for (MapleDisease debuff : cureDebuffs) {
                applyfrom.dispelDebuff(debuff);
            }
        }
        List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<Pair<MapleStat, Integer>>(2);
        if (!primary && isResurrection()) {
            hpchange = applyto.getMaxHp();
            applyto.setStance(0);
        }
        if (isDispel() && makeChanceResult()) {
            applyto.dispelDebuffs();
        }
        if (isHeroWill()) {
            applyto.cancelAllDebuffs();
        }
        if (hpchange != 0) {
            if (hpchange < 0 && (-hpchange) > applyto.getHp()) {
                return false;
            }
            int newHp = applyto.getHp() + hpchange;
            if (newHp < 1) {
                newHp = 1;
            }
            applyto.setHp(newHp);
            hpmpupdate.add(new Pair<MapleStat, Integer>(MapleStat.HP, Integer.valueOf(applyto.getHp())));
        }
        if (mpchange != 0) {
            if (mpchange < 0 && (-mpchange) > applyto.getMp()) {
                return false;
            }
            applyto.setMp(applyto.getMp() + mpchange);
            hpmpupdate.add(new Pair<MapleStat, Integer>(MapleStat.MP, Integer.valueOf(applyto.getMp())));
        }
        applyto.getClient().getSession().write(MaplePacketCreator.updatePlayerStats(hpmpupdate, true));
        
        if (moveTo != -1 && !skill) {
            MapleMap target = null;
            boolean nearest = false;
            if (moveTo == 999999999) {
                nearest = true;
                if (applyto.getMap().getReturnMapId() != 999999999) {
                    target = applyto.getMap().getReturnMap();
                }
            } else {
                target = ChannelServer.getInstance(applyto.getClient().getChannel()).getMapFactory().getMap(moveTo);
                int targetMapId = target.getId() / 10000000;
                int charMapId = applyto.getMapId() / 10000000;
                if (targetMapId != 60 && charMapId != 61) {
                    if (targetMapId != 21 && charMapId != 20) {
                        if (targetMapId != 12 && charMapId != 10) {
                            if (targetMapId != 10 && charMapId != 12) {
                                if (targetMapId != charMapId) {
                                    log.info("人物 {} 尝试回到一个非法的位置 ({}->{})", new Object[]{applyto.getName(), applyto.getMapId(), target.getId()});
                                    applyto.getClient().disconnect();
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
            if (target == applyto.getMap() || nearest && applyto.getMap().isTown()) {
                return false;
            }
        }
        
        if (isShadowClaw()) {
            MapleInventory use = applyto.getInventory(MapleInventoryType.USE);
            MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
            int projectile = 0;
            for (int i = 0; i < 255; i++) { // impose order...
                IItem item = use.getItem((byte) i);
                if (item != null) {
                    boolean isStar = mii.isThrowingStar(item.getItemId());
                    if (isStar && item.getQuantity() >= 200) {
                        projectile = item.getItemId();
                        break;
                    }
                }
            }
            if (projectile == 0) {
                return false;
            } else {
                MapleInventoryManipulator.removeById(applyto.getClient(), MapleInventoryType.USE, projectile, 200, false, true);
            }
        }
        if (overTime) {
            applyBuffEffect(applyfrom, applyto, primary);
        }
        if (primary && (overTime || isHeal())) {
            //组队处理
            applyBuff(applyfrom);
        }
        if (primary && isMonsterBuff()) {
            //给一定范围内的怪物施加buff
            applyMonsterBuff(applyfrom);
        }
        SummonMovementType summonMovementType = getSummonMovementType();
        if (summonMovementType != null && pos != null) {
            //如果存在这个召唤兽就先取消一次
            int summonId = sourceid;
            //MapleSummon summon = applyfrom.getSummons().get(summonId);
            MapleSummon summon = applyfrom.getSummon(summonId);
            if (!(summon == null 
                    || summon.getSkill() == 机械师.磁场 && applyfrom.getSummonAmount(机械师.磁场) < 3 
                    || summon.getSkill() == 弩骑.地雷_自爆 
                    || summon.getSkill() == 机械师.机器人工厂_机器人 )) {
                //System.out.println("在召唤召唤兽的时候检测到已经存在此召唤兽 先进行取消");
                applyfrom.getMap().broadcastMessage(MaplePacketCreator.removeSpecialMapObject(summon, true));
                applyfrom.getMap().removeMapObject(summon);
                applyfrom.removeVisibleMapObject(summon);
                applyfrom.removeSummon(summonId);
            }
            MapleSummon tosummon = new MapleSummon(applyfrom, sourceid, pos, summonMovementType);
            if (!tosummon.isPuppet()) {
                applyfrom.getCheatTracker().resetSummonAttack();
            }
            applyfrom.getMap().spawnSummon(tosummon);
            //applyfrom.getSummons().put(sourceid, tosummon);
            applyfrom.putSummon(sourceid, tosummon);
            tosummon.addHP(x);
            if (isBeholder()) {
                tosummon.addHP(1);
            }
        } else if (isMagicDoor()) {
            Point doorPosition = new Point(applyto.getPosition());
            MapleDoor door = new MapleDoor(applyto, doorPosition);
            applyto.getMap().spawnDoor(door);
            applyto.addDoor(door);
            door = new MapleDoor(door);
            applyto.addDoor(door);
            door.getTown().spawnDoor(door);
            if (applyto.getParty() != null) {
                //更新组队
                applyto.silentPartyUpdate();
            }
            applyto.disableDoor();
        } else if (isMist()) {
            Rectangle bounds = calculateBoundingBox(applyfrom.getPosition(), applyfrom.isFacingLeft());
            MapleMist mist = new MapleMist(bounds, applyfrom, this);
            applyfrom.getMap().spawnMist(mist, getDuration(), false);
        } else if (isTimeLeap()) {
            for (PlayerCoolDownValueHolder i : applyto.getAllCooldowns()) {
                if (i.skillId != 拳手.伺机待发) {
                    applyto.removeCooldown(i.skillId);
                }
            }
        } else if (is传送门()) { 
            if(applyto.getDoors2().size() >= 2) {
                for(MapleDoor2 olddoor2 : applyto.getDoors2()) {
                    if(olddoor2.isFirst() == firstDoor) {
                        if(olddoor2.isFirst()) {
                            applyto.cancelDoor2_1();
                        } else {
                            applyto.cancelDoor2_2();
                        }
                        applyto.getMap().broadcastMessage(MaplePacketCreator.取消传送门(applyto.getId(), olddoor2.isFirst()));
                        log.info("取消的门："+olddoor2.isFirst());
                        applyto.getMap().removeMapObject(olddoor2);
                        applyto.getDoors2().remove(olddoor2);
                        break;
                    }
                }
            }
            MapleDoor2 door2 = new MapleDoor2(applyto, applyto.getPosition(), firstDoor);
            applyto.addDoor2(door2);
            applyto.getMap().spawnDoor2(door2);
            applyto.cancelDoor2(door2, this.duration); //设置多久时间后取消
            if(firstDoor) {
                firstDoor = false;
            } else {
                firstDoor = true;
            }
        }
        if (isHide()) {
            if (applyto.isHidden()) {
                applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.removePlayerFromMap(applyto.getId()), false);
                applyto.getClient().getSession().write(MaplePacketCreator.giveGmHide(true));
            } else {
                applyto.getClient().getSession().write(MaplePacketCreator.giveGmHide(false));
                applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapobject(applyto), false);
                for (MaplePet pet : applyto.getPets()) {
                    if (pet != null) {
                        applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.showPet(applyto, pet, false, false), false);
                    }
                }
            }
        }
        return true;
    }

    public boolean applyReturnScroll(MapleCharacter applyto) {
        if (moveTo != -1 && !skill) {
            if (applyto.getMap().getReturnMapId() != applyto.getMapId()) {
                MapleMap target;
                if (moveTo == 999999999) {
                    target = applyto.getMap().getReturnMap();
                } else {
                    target = ChannelServer.getInstance(applyto.getClient().getChannel()).getMapFactory().getMap(moveTo);
                    if (target.getId() / 10000000 != 60 && applyto.getMapId() / 10000000 != 61) {
                        if (target.getId() / 10000000 != 21 && applyto.getMapId() / 10000000 != 20) {
                            if (target.getId() / 10000000 != applyto.getMapId() / 10000000) {
                                return false;
                            }
                        }
                    }
                }
                applyto.changeMap(target, target.getPortal(0));
                return true;
            }
        }
        return false;
    }

    private void applyBuff(MapleCharacter applyfrom) {
        if (isPartyBuff() && (applyfrom.getParty() != null || isGMBuff())) {
            Rectangle bounds = calculateBoundingBox(applyfrom.getPosition(), applyfrom.isFacingLeft());
            List<MapleMapObject> affecteds = applyfrom.getMap().getMapObjectsInRect(bounds, Arrays.asList(MapleMapObjectType.PLAYER));
            List<MapleCharacter> affectedp = new ArrayList<MapleCharacter>(affecteds.size());
            for (MapleMapObject affectedmo : affecteds) {
                MapleCharacter affected = (MapleCharacter) affectedmo;
                //this is new and weird...
                if (affected != null && isHeal() && affected != applyfrom && affected.getParty() == applyfrom.getParty() && affected.isAlive()) {
                    int expadd = (int) ((calcHPChange(applyfrom, true) / 10) * (applyfrom.getClient().getChannelServer().getExpRate() + ((Math.random() * 10) + 30)) * (Math.floor(Math.random() * (applyfrom.getSkillLevel(SkillFactory.getSkill(2301002))) / 100) * (applyfrom.getLevel() / 30)));
                    if (affected.getHp() < affected.getMaxHp() - affected.getMaxHp() / 20) {
                        applyfrom.gainExp(expadd, true, false, false);
                    }
                }
                if (affected != applyfrom && (isGMBuff() || applyfrom.getParty().equals(affected.getParty()))) {
                    boolean isRessurection = isResurrection();
                    if ((isRessurection && !affected.isAlive()) || (!isRessurection && affected.isAlive())) {
                        affectedp.add(affected);
                    }
                    if (isTimeLeap()) {
                        for (PlayerCoolDownValueHolder i : affected.getAllCooldowns()) {
                            if (i.skillId != 拳手.伺机待发) { //伺机待发
                                affected.removeCooldown(i.skillId);
                            }
                        }
                    }
                }
            }
            for (MapleCharacter affected : affectedp) {
                // TODO actually heal (and others) shouldn't recalculate everything
                // for heal this is an actual bug since heal hp is decreased with the number
                // of affected players
                applyTo(applyfrom, affected, false, null);
                affected.getClient().getSession().write(MaplePacketCreator.showOwnBuffEffect(sourceid, 2));
                affected.getMap().broadcastMessage(affected, MaplePacketCreator.showBuffeffect(affected.getId(), sourceid, 2, (byte) 3), false);
            }
        }
    }

    private void applyMonsterBuff(MapleCharacter applyfrom) {
        Rectangle bounds = calculateBoundingBox(applyfrom.getPosition(), applyfrom.isFacingLeft());
        List<MapleMapObject> affected = applyfrom.getMap().getMapObjectsInRect(bounds, Arrays.asList(MapleMapObjectType.MONSTER));
        ISkill skill_ = SkillFactory.getSkill(sourceid);
        int i = 0;
        for (MapleMapObject mo : affected) {
            MapleMonster monster = (MapleMonster) mo;
            if (makeChanceResult()) {
                monster.applyStatus(applyfrom, new MonsterStatusEffect(getMonsterStati(), skill_, false), isPoison(), getDuration());
            }
            i++;
            if (i >= mobCount) {
                break;
            }
        }
    }

    public Rectangle calculateBoundingBox(Point posFrom, boolean facingLeft) {
        Point mylt;
        Point myrb;
        if (facingLeft) {
            System.out.println("facingLeft为真");
            mylt = new Point(lt.x + posFrom.x, lt.y + posFrom.y);
            myrb = new Point(rb.x + posFrom.x, rb.y + posFrom.y);
        } else {
            System.out.println("facingLeft为假");
            myrb = new Point(lt.x * -1 + posFrom.x, rb.y + posFrom.y);
            mylt = new Point(rb.x * -1 + posFrom.x, lt.y + posFrom.y);
        }
        Rectangle bounds = new Rectangle(mylt.x, mylt.y, myrb.x - mylt.x, myrb.y - mylt.y);
        return bounds;
    }
    
    public void silentApplyBuff(MapleCharacter chr, long starttime) {
        int localDuration = duration;
        localDuration = alchemistModifyVal(chr, localDuration, false);
        CancelEffectAction cancelAction = new CancelEffectAction(chr, this, starttime);
        ScheduledFuture<?> schedule = TimerManager.getInstance().schedule(cancelAction, ((starttime + localDuration) - System.currentTimeMillis()));
        chr.registerEffect(this, starttime, schedule);
        SummonMovementType summonMovementType = getSummonMovementType();
        if (summonMovementType != null) {
            final MapleSummon tosummon = new MapleSummon(chr, sourceid, chr.getPosition(), summonMovementType);
            if (!tosummon.isPuppet()) {
                chr.getCheatTracker().resetSummonAttack();
                //chr.getSummons().put(sourceid, tosummon);
                chr.putSummon(sourceid, tosummon);
                tosummon.addHP(x);
            }
        }
    }
    
    public boolean isMonsterRiding() {
        return isNotItemMount() || isNormalMonsterRiding();
    }
    
    public boolean isNormalMonsterRiding() {
        return sourceid == 新手.骑兽技能
                || sourceid == 初心者.骑兽技能 
                || sourceid == 战神.骑兽技能
                || sourceid == 龙神.骑兽技能
                || sourceid == 预备兵.骑兽技能 ;
    }
    
    public boolean isNotCancelBuffFirst(int skillid) {
        switch(skillid){
            case 弩手.替身术: // 射手 - 替身术
            case 弓手.替身术: // 游侠 - 替身术
            case 风灵使者.替身术:// 风灵使者 - 替身术
            case 枪手.章鱼炮台: // 大幅 - 章鱼炮台
            case 枪手.超级章鱼炮台: // 船长 - 超级章鱼炮台
            case 双刀.傀儡召唤: // 暗影双刀 - 傀儡召唤
            case 刀飞.黑暗杂耍: // 独行客 - 黑暗杂耍
            case 标飞.黑暗杂耍: // 无影人 - 黑暗杂耍
            case 机械师.磁场: // 机械师 - 磁场
            case 机械师.加速器: // 机械师 - 加速器：EX-7
            case 机械师.治疗机器人: // 机械师 - 治疗机器人：H-LX
            case 机械师.战争机器_泰坦: // 机械师 - 战争机器：泰坦
            case 机械师.机器人工厂_RM1: // 机械师 - 机器人工厂：RM1
            case 机械师.放大器_AF_11: // 机械师 - 放大器：AF-11
            case 弩骑.地雷_自爆: // 弩骑 - 地雷 自爆
            case 弩骑.野性陷阱: // 弩骑 野性陷阱
            case 弩手.金鹰召唤: // 射手 - 金鹰召唤
            case 弓手.银鹰召唤: // 游侠 - 银鹰召唤
            case 牧师.圣龙召唤: // 祭司 - 圣龙召唤
            case 弩手.冰凤凰: // 神射手 - 冰凤凰
            case 弓手.火凤凰: // 箭神 - 火凤凰
            case 枪手.海鸥空袭: // 大幅 - 海鸥空袭
            case 弩骑.银鹰: // 弩骑 银鹰
            case 机械师.机器人工厂_机器人: // 机器人工厂召唤技能
            case 战法.重生: //幻灵 重生
            case 龙骑.灵魂助力: // 黑骑士 - 灵魂助力
            case 火毒.火魔兽: // 火毒导师 - 冰破魔兽
            case 冰雷.冰破魔兽: // 冰雷导师 - 火魔兽
            case 牧师.强化圣龙: // 主教 - 强化圣龙
            case 魂骑士.魂精灵: // 魂骑士 - 魂精灵
            case 炎术士.炎精灵: // 炎术士 - 炎精灵
            case 风灵使者.风精灵: // 风灵使者 - 风精灵
            case 夜行者.夜精灵: // 夜行者  - 夜精灵
            case 奇袭者.雷精灵: // 奇袭者 - 雷精灵
            case 炎术士.火魔兽: // 炎术士 - 火魔兽
            case 机械师.人造卫星: // 机械师 - 人造卫星
            case 机械师.人造卫星2: // 机械师 - 人造卫星
            case 机械师.人造卫星3: // 机械师 - 人造卫星
            case 战法.进阶黑暗灵气:
            case 战法.进阶蓝色灵气:
            case 战法.进阶黄色灵气:
                return true;
        }
        return false;
    }
    
    public boolean isGiveForeignBuff(){
        return isDs() 
                || isCombo() 
                || isShadowPartner()
                || isSoulArrow()
                || isMorph()
                || isPirateMorph()
                //|| isLingQi()
                ;
    }

    public boolean isNotItemMount() {
        if (getMountID() == -1)
            return false;
        return true;
    }
    
    public int getMountID() {
        int skillmod = -1;
        skillmod = sourceid;
        switch (skillmod) {
            case 1013:
            case 10001014:
            case 20001046:
            case 20011046:
            case 30001013:
                return 1932001; //宇宙船
            case 1015:
            case 10001016:
            case 30001015:
                return 1932002; //太空射线
            case 1017:
            case 1018:
            case 1050:
            case 10001019:
            case 10001022:
            case 10001050:
            case 20001019:
            case 20001022:
            case 20001050:
            case 20011018:
            case 30001017:
            case 30001018:
                return 1932003; //白雪人骑宠
            case 1019:
            case 10001023:
            case 20001023:
            case 20011019:
            case 30001019:
                return 1932005; //魔女的扫把
            case 1025:
            case 10001025:
            case 20001025:
            case 20011025:
            case 30001025:
                return 1932006; //突击！木马
            case 1027:
            case 10001027:
            case 20001027:
            case 20011027:
            case 30001027:
                return 1932007; //鳄鱼
            case 1028:
            case 10001028:
            case 20001028:
            case 20011028:
            case 30001028:
                return 1932008; //透明自行车
            case 1029:
            case 10001029:
            case 20001029:
            case 20011029:
            case 30001029:
                return 1932009; //粉色电单车
            case 1030:
            case 10001030:
            case 20001030:
            case 20011030:
            case 30001030:
                return 1932011; //筋斗云
            case 1031:
            case 10001031:
            case 20001031:
            case 20011031:
            case 30001031:
                return 1932010; //蝙蝠怪
            case 1033:
            case 10001033:
            case 20001033:
            case 20011033:
            case 30001033:
                return 1932013; //可以开着赛车移动。
            case 1034:
            case 10001034:
            case 20001034:
            case 20011034:
            case 30001034:
                return 1932014; //虎哥
            case 1035:
            case 10001035:
            case 20001035:
            case 20011035:
            case 30001035:
                return 1932012; //蝙蝠魔先生
            case 1036:
            case 10001036:
            case 20001036:
            case 20011036:
            case 30001036:
                return 1932017; //狮子王
            case 1037:
            case 10001037:
            case 20001037:
            case 20011037:
            case 30001037:
                return 1932018; //独角兽
            case 1039:
            case 10001039:
            case 20001039:
            case 20011039:
            case 30001039:
                return 1932020; //田园红卡车
            case 1040:
            case 10001040:
            case 20001040:
            case 20011040:
            case 30001040:
                return 1932021; //恶魔石像
            case 1042:
            case 10001042:
            case 20001042:
            case 20011042:
            case 30001042:
                return 1932022; //圣兽 提拉奥斯
            case 1044:
            case 10001044:
            case 20001044:
            case 20011044:
            case 30001044:
                return 1932023; //花蘑菇
            case 1049:
            case 10001049:
            case 20001049:
            case 20011049:
            case 30001049:
                return 1932025; //梦魇
            case 1051:
            case 10001051:
            case 20001051:
            case 20011051:
            case 30001051:
                return 1932026; //鸵鸟
            case 1052:
            case 10001052:
            case 20001052:
            case 20011052:
            case 30001052:
                return 1932027; //热气球
            case 1053:
            case 10001053:
            case 20001053:
            case 20011053:
            case 30001053:
                return 1932028; //变形金刚
            case 1063:
            case 10001063:
            case 20001063:
            case 20011063:
            case 30001063:
                return 1932034; //摩托车
            case 1064:
            case 10001064:
            case 20001064:
            case 20011064:
            case 30001064:
                return 1932035; //超能套装
            case 1069:
            case 10001069:
            case 20001069:
            case 20011069:
            case 30001069:
                return 1932038; //猫头鹰
            case 1096:
            case 10001096:
            case 20001096:
            case 20011096:
            case 30001096:
                return 1932045; //巨无霸兔子
            case 1101:
            case 10001101:
            case 20001101:
            case 20011101:
            case 30001101:
                return 1932046; //兔兔加油
            case 1102:
            case 10001102:
            case 20001102:
            case 20011102:
            case 30001102:
                return 1932047; //兔子车夫
            case 1106:
            case 10001106:
            case 20001106:
            case 20011106:
            case 30001106:
                return 1932048; //福袋
            case 1118:
            case 10001118:
            case 20001118:
            case 20011118:
            case 30001118:
                return 1932060; //妮娜的魔法阵
            case 1054:
            case 10001054:
            case 20001054:
            case 20011054:
            case 30001054:
                return 1932062; //走路鸡
            case 1121:
            case 10001121:
            case 20001121:
            case 20011121:
            case 30001121:
                return 1932063; //青蛙
            case 1122:
            case 10001122:
            case 20001122:
            case 20011122:
            case 30001122:
                return 1932064; //小龟龟
            case 1123:
            case 10001123:
            case 20001123:
            case 20011123:
            case 30001123:
                return 1932065; //无辜水牛
            case 1124:
            case 10001124:
            case 20001124:
            case 20011124:
            case 30001124:
                return 1932066; //玩具坦克
            case 1129:
            case 10001129:
            case 20001129:
            case 20011129:
            case 30001129:
                return 1932071; //维京战车
            case 1130:
            case 10001130:
            case 20001130:
            case 20011130:
            case 30001130:
                return 1932072; //打豆豆机器人
            case 1136:
            case 10001136:
            case 20001136:
            case 20011136:
            case 30001136:
                return 1932078; //莱格斯的豺犬
            case 1138:
            case 10001138:
            case 20001138:
            case 20011138:
            case 30001138:
                return 1932080; //跑车
            case 1139:
            case 10001139:
            case 20001139:
            case 20011139:
            case 30001139:
                return 1932081; //拿破仑的白马
            case 1158:
            case 10001158:
            case 20001158:
            case 20011158:
            case 30001158:
                return 1932083; //机动巡逻车(准乘4人)
            case 1148:
            case 10001148:
            case 20001148:
            case 20011148:
            case 30001148:
                return 1992005; //暗光龙
            case 5221006:
                return 1932000; //武装
            case 35001002:
                return 1932016; //金属机甲 原型
            case 弩骑.美洲豹骑士:
                return 1932015; //美洲豹骑士
            default:
                return -1;
        }
    }
    
    private void applyBuffEffect(final MapleCharacter applyfrom, final MapleCharacter applyto, boolean primary) {
        if (!this.isMonsterRiding() && !isNotCancelBuffFirst(sourceid)) { 
            //System.out.println("在givebuff之前先cancel一下 防止已有buff又被give一次");
            applyto.cancelEffect(this, true, -1);
        }
        
        List<Pair<MapleBuffStat, Integer>> localstatups = statups;
        int localDuration = duration;
        int localsourceid = sourceid;
        int skillid = 0;
        int itemid = 0;
        if (isMonsterRiding()) {
            int ridingitemid = 0; //骑宠的itemid
            IItem mount = applyfrom.getInventory(MapleInventoryType.EQUIPPED).getItem((byte) -18);
            if (mount != null && isNormalMonsterRiding())
                ridingitemid = mount.getItemId();
            else if (isNotItemMount())
                ridingitemid = getMountID();
            itemid = ridingitemid;
            skillid = sourceid;
            localDuration = 2100000000; //让持续时间无限长
            applyto.setUsingMount(itemid, skillid);
            //applyto.getMount().startSchedule(); //骑宠疲劳
            localstatups = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.骑宠1, 0));
        } else if (is骰子()) {
            int type = new Random().nextInt(6) + 1;
            localstatups = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.幸运骰子, type));
        }
        
        if (primary) 
            localDuration = alchemistModifyVal(applyfrom, localDuration, false);
        
        if (localstatups.size() > 0) 
            if ((isDash() || isTornado()) && applyfrom.getBuffedValue(MapleBuffStat.疾驰_龙卷风) == null) {
                //System.out.println("龙卷风/疾驰"+localstatups);
                applyto.getClient().getSession().write(MaplePacketCreator.giveDashOrTornado(localstatups, sourceid, localDuration / 1000));
            } else if (isInfusion()) {
                System.out.println("极速领域");
                applyto.getClient().getSession().write(MaplePacketCreator.giveInfusion(sourceid, localDuration / 1000, x));
            } else if (isMonsterRiding()) {
                System.out.println("骑宠");
                applyto.getClient().getSession().write(MaplePacketCreator.giveMonsterRidingBuff(applyto, itemid, skillid, localstatups, localDuration));
            } else if (isSkillBianShen()) {
                System.out.println("变身技能");
                applyto.getClient().getSession().write(MaplePacketCreator.giveSkillBianShen(applyto, localsourceid, localDuration, localstatups));
            } else if(sourceid == 骑士.祝福护甲){
                System.out.println("祝福护甲技能");
                applyto.getClient().getSession().write(MaplePacketCreator.giveArmorBuff(applyto, localDuration, localstatups, localstatups.get(1).getRight()));
            } else if (is能量获得()){
                System.out.println("能量获得技能");
                applyto.getClient().getSession().write(MaplePacketCreator.givePirateBuff(0, localDuration, localstatups));
            } else if (is骰子()){
                System.out.println("幸运骰子技能 点数："+localstatups.get(0).getRight());
                applyto.getClient().getSession().write(MaplePacketCreator.骰子(localsourceid, localstatups, localDuration, localstatups.get(0).getRight()));
            } else {
                System.out.println("普通技能");
                applyto.getClient().getSession().write(MaplePacketCreator.giveBuff(applyto, (skill ? localsourceid : -localsourceid), localDuration, localstatups));
            }
        
        if (isMonsterRiding()) {
            List<Pair<MapleBuffStat, Integer>> stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.骑宠1, 1));
            applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.showMonsterRiding(applyto, stat, itemid, skillid, localDuration), false);
            
        } else if(isGiveForeignBuff()) { //总判断 记得要在下面出现的判断记得先在这里加
             List<Pair<MapleBuffStat, Integer>> stat = null;
        if (isDs()) 
            stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DARKSIGHT, 0));
        else if (isCombo()) 
            stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.COMBO, 1));
        else if (isShadowPartner()) 
            stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SHADOWPARTNER, 0));
        else if (isSoulArrow()) 
            stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SOULARROW, 0));
        else if (isMorph()) 
            stat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MORPH, morphId));
        else if (isPirateMorph()) {
            stat = new ArrayList<Pair<MapleBuffStat, Integer>>();
            stat.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.SPEED, Integer.valueOf(speed)));
            stat.add(new Pair<MapleBuffStat, Integer>(MapleBuffStat.MORPH, Integer.valueOf(morphId)));
        }
        if(stat == null)
            System.out.println("stat == null");
        applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.giveForeignBuff(applyto, stat, this), false);
        } else if (isEnrage())
            applyto.handleOrbconsume();
        else if (isTimeLeap()) {
            for (PlayerCoolDownValueHolder i : applyto.getAllCooldowns()) {
                if (i.skillId != 拳手.伺机待发) {
                    applyto.removeCooldown(i.skillId);
                }
            }
        } else if (isLingQi()) {
            MapleBuffStat stat2 = null;
            if (sourceid == 战法.黑暗灵气 || sourceid == 战法.进阶黑暗灵气)
                stat2 = MapleBuffStat.黑暗灵气;
            else if (sourceid == 战法.蓝色灵气 || sourceid == 战法.进阶蓝色灵气)
                stat2 = MapleBuffStat.蓝色灵气;
            else if (sourceid == 战法.黄色灵气 || sourceid == 战法.进阶黄色灵气) 
                stat2 = MapleBuffStat.黄色灵气;
            applyto.getClient().getSession().write(MaplePacketCreator.giveBuff(applyto, localsourceid , localDuration, Collections.singletonList(new Pair<MapleBuffStat, Integer>(stat2, x))));
        }
        
        if (localstatups.size() > 0) {
            long starttime = System.currentTimeMillis();
            CancelEffectAction cancelAction = new CancelEffectAction(applyto, this, starttime);
            ScheduledFuture<?> schedule = TimerManager.getInstance().schedule(cancelAction, localDuration);
            applyto.registerEffect(this, starttime, schedule);
        }
        if (primary && !isHide()) 
            if (isDash()) {
                //applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.showDashEffecttoOthers(applyto.getId(), localstatups, localDuration / 1000), false);
            } else if (isInfusion()) {
                applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.giveForeignInfusion(applyto.getId(), sourceid, x, localDuration / 1000), false);
            } else if (is骰子()) {
                applyto.getClient().getSession().write(MaplePacketCreator.机械技能特效(3, localstatups.get(0).getRight(), applyfrom.getLevel(), sourceid, applyfrom.getSkillLevel(sourceid), 1));
                applyto.getMap().broadcastMessage(MaplePacketCreator.机械技能特效(applyto.getId(), 3, localstatups.get(0).getRight(), applyto.getLevel(), sourceid, applyto.getSkillLevel(sourceid), 1));
            } else {
                applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.showBuffeffect(applyto.getId(), sourceid, 1, (byte) 3), false);
            }
    }

    private int calcHPChange(MapleCharacter applyfrom, boolean primary) {
        int hpchange = 0;
        if (hp != 0) {
            if (!skill) {
                if (primary) {
                    hpchange += alchemistModifyVal(applyfrom, hp, true);
                } else {
                    hpchange += hp;
                }
            } else { // assumption: this is heal
                hpchange += makeHealHP(hp / 100.0, applyfrom.getTotalMagic(), 3, 5);
            }
        }
        if (hpR != 0) {
            hpchange += (int) (applyfrom.getCurrentMaxHp() * hpR);
            //applyfrom.checkBerserk();
        }
        if (primary) {
            if (hpCon != 0) {
                hpchange -= hpCon;
            }
        }
        if (isChakra()) {
            hpchange += makeHealHP(getY() / 100.0, applyfrom.getTotalLuk(), 2.3, 3.5);
        }
        if (isPirateMpRecovery()) {
            hpchange -= ((getX() / 100.0) * applyfrom.getCurrentMaxHp());
        }
        return hpchange;
    }

    private int makeHealHP(double rate, double stat, double lowerfactor, double upperfactor) {
        int maxHeal = (int) (stat * upperfactor * rate);
        int minHeal = (int) (stat * lowerfactor * rate);
        return (int) ((Math.random() * (maxHeal - minHeal + 1)) + minHeal);
    }

    private int calcMPChange(MapleCharacter applyfrom, boolean primary) {
        int mpchange = 0;
        if (mp != 0) {
            if (primary) {
                mpchange += alchemistModifyVal(applyfrom, mp, true);
            } else {
                mpchange += mp;
            }
        }
        if (mpR != 0) {
            mpchange += (int) (applyfrom.getCurrentMaxMp() * mpR);
        }
        if (primary) {
            if (mpCon != 0) {
                double mod = 1.0;
                boolean isAFpMage = applyfrom.getJob().isA(MapleJob.FP_MAGE);
                if (isAFpMage || applyfrom.getJob().isA(MapleJob.IL_MAGE)) {
                    ISkill amp;
                    if (isAFpMage) {
                        amp = SkillFactory.getSkill(火毒.魔力激化);
                    } else {
                        amp = SkillFactory.getSkill(冰雷.魔力激化);
                    }
                    int ampLevel = applyfrom.getSkillLevel(amp);
                    if (ampLevel > 0) {
                        MapleStatEffect ampStat = amp.getEffect(ampLevel);
                        mod = ampStat.getX() / 100.0;
                    }
                }
                mpchange -= mpCon * mod;
                if (applyfrom.getBuffedValue(MapleBuffStat.INFINITY) != null) {
                    mpchange = 0;
                }
            }
        }
        if (isPirateMpRecovery()) {
            mpchange += (((getY() * getX()) / 10000.0) * applyfrom.getCurrentMaxHp());
        }
        return mpchange;
    }

    private int alchemistModifyVal(MapleCharacter chr, int val, boolean withX) {
        if (!skill && (chr.getJob().isA(MapleJob.HERMIT) || chr.getJob().isA(MapleJob.NIGHTLORD))) {
            MapleStatEffect alchemistEffect = getAlchemistEffect(chr);
            if (alchemistEffect != null) {
                return (int) (val * ((withX ? alchemistEffect.getX() : alchemistEffect.getY()) / 100.0));
            }
        }
        return val;
    }

    private MapleStatEffect getAlchemistEffect(MapleCharacter chr) {
        ISkill alchemist = SkillFactory.getSkill(标飞.药剂精通);
        int alchemistLevel = chr.getSkillLevel(alchemist);
        if (alchemistLevel == 0) {
            return null;
        }
        return alchemist.getEffect(alchemistLevel);
    }

    public void setSourceId(int newid) {
        sourceid = newid;
    }
    
    public void setLt(Point Lt) {
        lt = Lt;
    }
    
    public void setRb(Point Rb) {
        rb = Rb;
    }
            
    private boolean isGMBuff() {
        if(!skill)
            return false;
        switch (sourceid) {
            case 新手.英雄之回声: // 英雄之回声
            case 管理员.完美治愈: // 完美治愈
            case 管理员.上乘轻功:// 上乘轻功
            case 管理员.神圣祈祷:// 神圣祈祷
            case 管理员.枫印祝福:// 枫印祝福
            case 管理员.普天复活:// 普天复活
            case 管理员.神圣之火:// 神圣之火
                return true;
            default:
                return false;
        }
    }

    private boolean isMonsterBuff() {
        //一定范围内给怪物Buff的技能 而且要有几率 即prop节点 否则直接在specialMove类获取Monster oid处理
        if (!skill) {
            return false;
        }
        switch (sourceid) {
            case 骑士.压制术:
            case 火毒.缓速术:
            case 冰雷.缓速术:
            case 冰雷.封印术:
            case 火毒.封印术:
            case 牧师.巫毒术:
            case 标飞.影网术:
            case 夜行者.影网术:
            case 标飞.忍者伏击:
            case 刀飞.忍者伏击:
            case 炎术士.缓速术:
            case 炎术士.封印术:
            case 龙神.火焰喷射:
            case 龙神.缓速术:
            case 龙神.冰点寒气:
            case 龙神.鬼刻符:
            case 双刀.闪光弹:
                return true;
        }
        return false;
    }

    private boolean isPartyBuff() {
        if (lt == null || rb == null || !skill) {
            return false;
        }
        //如果技能有范围 但是不是组队技能的话就在这里false
        switch(sourceid){
            case 骑士.火焰冲击:
            case 骑士.寒冰冲击:
            case 骑士.雷鸣冲击:
            case 骑士.神圣冲击:
            case 冰雷.快速移动精通:
            case 火毒.快速移动精通:
            case 牧师.快速移动精通:    
            case 战法.快速移动精通:
            case 机械师.火焰喷射器:
            case 机械师.强化火焰喷射器:
            case 机械师.金属机甲_导弹战车:
            case 双刀.暗影轻功:
            case 双刀.终极斩:
            case 双刀.荆棘:
            case 双刀.死亡猫头鹰:
            case 战神.冰雪矛:
            case 弩骑.吞噬_消化:
            case 魂骑士.灵魂属性:
            case 战法.飓风:
            case 奇袭者.雷鸣:
                return false;
        }
        return true;
    }

    public boolean isHeal() {
        return skill && (sourceid == 牧师.群体治愈 || sourceid == 管理员.完美治愈);
    }

    public boolean isResurrection() {
        return skill && (sourceid == 管理员.普天复活 || sourceid == 牧师.复活术);
    }

    public boolean isTimeLeap() {
        return skill && (sourceid == 拳手.伺机待发);
    }
    
    private boolean isInfusion() {
        return skill && (sourceid == 拳手.极速领域 || sourceid == 奇袭者.极速领域);
    }

    public int getHp() {
        return hp;
    }

    public int getMp() {
        return mp;
    }

    public int getMpCon() {
        return mpCon;
    }

    public int getWatk() {
        return watk;
    }

    public int getMatk() {
        return matk;
    }

    public int getWdef() {
        return wdef;
    }

    public int getMdef() {
        return mdef;
    }

    public int getAcc() {
        return acc;
    }

    public int getAvoid() {
        return avoid;
    }

    public int getHands() {
        return hands;
    }

    public int getSpeed() {
        return speed;
    }

    public int getJump() {
        return jump;
    }

    public int getDuration() {
        return duration;
    }

    public boolean isOverTime() {
        return overTime;
    }
    
    public int getEWatk() {
        return epad;
    }

    public int getEWdef() {
        return epdd;
    }

    public int getEMdef() {
        return emdd;
    }
    
    public List<Pair<MapleBuffStat, Integer>> getStatups() {
        return statups;
    }

    public boolean sameSource(MapleStatEffect effect) {
        return this.sourceid == effect.sourceid && this.skill == effect.skill;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getZ() {
        return z;
    }
    
    public double getZR() {
        return z / 100;
    }
    
    public int getT() {
        return t;
    }
    
    public int getDamage() {
        return damage;
    }

    public int getAttackCount() {
        return attackCount;
    }

    public int getMobCount() {
        return mobCount;
    }

    public int getBulletCount() {
        return bulletCount;
    }

    public int getBulletConsume() {
        return bulletConsume;
    }

    public int getMoneyCon() {
        return moneyCon;
    }

    public int getCooldown() {
        return cooldown;
    }

    public Map<MonsterStatus, Integer> getMonsterStati() {
        return monsterStatus;
    }

    public boolean isHide() {
        return skill && sourceid == 管理员.隐藏术;
    }

    public boolean isDragonBlood() {
        return skill && sourceid == 龙骑.龙之魂;
    }

    public boolean isBerserk() {
        return skill && sourceid == 龙骑.黑暗力量;
    }

    private boolean isDs() {
        return skill && sourceid == 飞侠.隐身术;
    }

    private boolean isCombo() {
        return (skill && sourceid == 勇士.斗气集中) || (skill && sourceid == 魂骑士.斗气集中);
    }

    private boolean isEnrage() {
        return skill && sourceid == 勇士.葵花宝典;
    }

    public boolean isBeholder() {
        return skill && sourceid == 龙骑.灵魂助力;
    }

    private boolean isShadowPartner() {
        return skill && 
                sourceid == 标飞.影分身
                || sourceid == 刀飞.影分身
                || sourceid == 夜行者.影分身
                || sourceid == 双刀.镜像分身;
    }

    private boolean isChakra() {
        return skill && sourceid == 刀飞.转化术;
    }

    private boolean isPirateMpRecovery() {
        return skill && sourceid == 拳手.生命分流;
    }
    
    public boolean isMagicDoor() {
        return skill && sourceid == 牧师.时空门;
    }

    public boolean isMesoGuard() {
        return skill && sourceid == 刀飞.金钱护盾;
    }

    public boolean isCharge() {
        return skill && sourceid >= 骑士.火焰冲击 && sourceid <= 骑士.雷鸣冲击;
    }

    public boolean isPoison() {
        return skill && (
                sourceid == 火毒.致命毒雾
                || sourceid == 火毒.毒雾术
                || sourceid == 火毒.火毒合击
                || sourceid == 夜行者.毒炸弹 
                || sourceid == 炎术士.火牢术屏障
                || sourceid == 战神.战神之审判);
    }

    private boolean isMist() {
        return skill && (
                sourceid == 火毒.致命毒雾
                || sourceid == 刀飞.烟幕弹 
                || sourceid == 战法.避难所 //避难所
                || sourceid == 龙神.极光恢复
                || sourceid == 机械师.放大器_AF_11
                || sourceid == 炎术士.火牢术屏障
                );
    }

    private boolean isSoulArrow() {
        return skill && (sourceid == 弓手.无形箭 || sourceid == 弩手.无形箭 || sourceid == 风灵使者.无形箭); // bow and crossbow
    }

    private boolean isShadowClaw() {
        return skill && sourceid == 标飞.暗器伤人;
    }

    private boolean isDispel() {
        return skill && (sourceid == 牧师.净化 || sourceid == 管理员.完美治愈);
    }

    private boolean isHeroWill() {
        return skill && (sourceid == 勇士.勇士的意志 || sourceid == 骑士.勇士的意志 || sourceid == 龙骑.勇士的意志 || sourceid == 火毒.勇士的意志 || sourceid == 冰雷.勇士的意志 || sourceid == 牧师.勇士的意志 || sourceid == 弓手.勇士的意志 || sourceid == 弩手.冒险岛勇士 || sourceid == 标飞.勇士的意志 || sourceid == 刀飞.勇士的意志 || sourceid == 拳手.勇士的意志 || sourceid == 枪手.勇士的意志 || sourceid == 战神.勇士的意志 || sourceid == 龙神.勇士的意志 || sourceid == 战法.勇士的意志 || sourceid == 弩骑.勇士的意志 || sourceid == 机械师.勇士的意志);
    }

    private boolean isDash() {
        return skill && sourceid == 海盗.疾驰;
    }

    public boolean isPirateMorph() { //海盗变身
        return skill && (sourceid == 拳手.超人变形 || sourceid == 拳手.超级变身 || sourceid == 风灵使者.信天翁 || sourceid == 奇袭者.超人变形);
    }

    public boolean isMorph() {
        return morphId > 0;
    }

    public int getMorph() {
        return morphId;
    }

    public boolean isSummon() {
        return getSummonMovementType() != null && !isBeholder();
    }

    public SummonMovementType getSummonMovementType() {
        if (!skill) {
            return null;
        }
        switch (sourceid) {
            case 弩手.替身术: // 射手 - 替身术
            case 弓手.替身术: // 游侠 - 替身术
            case 风灵使者.替身术:// 风灵使者 - 替身术
            case 枪手.章鱼炮台: // 大幅 - 章鱼炮台
            case 枪手.超级章鱼炮台: // 船长 - 超级章鱼炮台
            case 双刀.傀儡召唤: // 暗影双刀 - 傀儡召唤
            case 刀飞.黑暗杂耍: // 独行客 - 黑暗杂耍
            case 标飞.黑暗杂耍: // 无影人 - 黑暗杂耍
            case 机械师.磁场: // 机械师 - 磁场
            case 机械师.加速器: // 机械师 - 加速器：EX-7
            case 机械师.治疗机器人: // 机械师 - 治疗机器人：H-LX
            case 机械师.战争机器_泰坦: // 机械师 - 战争机器：泰坦
            case 机械师.机器人工厂_RM1: // 机械师 - 机器人工厂：RM1
            case 机械师.放大器_AF_11: // 机械师 - 放大器：AF-11
            case 弩骑.地雷_自爆: // 弩骑 - 地雷 自爆
            case 弩骑.野性陷阱: // 弩骑 野性陷阱
                return SummonMovementType.STATIONARY;
            case 弩手.金鹰召唤: // 射手 - 金鹰召唤
            case 弓手.银鹰召唤: // 游侠 - 银鹰召唤
            case 牧师.圣龙召唤: // 祭司 - 圣龙召唤
            case 弩手.冰凤凰: // 神射手 - 冰凤凰
            case 弓手.火凤凰: // 箭神 - 火凤凰
            case 枪手.海鸥空袭: // 大幅 - 海鸥空袭
            case 弩骑.银鹰: // 弩骑 银鹰
                return SummonMovementType.CIRCLE_FOLLOW;
            case 机械师.机器人工厂_机器人: // 机器人工厂召唤技能
            case 战法.重生: //幻灵 重生
                return SummonMovementType.UNKNOWN;
            case 龙骑.灵魂助力: // 黑骑士 - 灵魂助力
            case 火毒.火魔兽: // 火毒导师 - 冰破魔兽
            case 冰雷.冰破魔兽: // 冰雷导师 - 火魔兽
            case 牧师.强化圣龙: // 主教 - 强化圣龙
            case 魂骑士.魂精灵: // 魂骑士 - 魂精灵
            case 炎术士.炎精灵: // 炎术士 - 炎精灵
            case 风灵使者.风精灵: // 风灵使者 - 风精灵
            case 夜行者.夜精灵: // 夜行者  - 夜精灵
            case 奇袭者.雷精灵: // 奇袭者 - 雷精灵
            case 炎术士.火魔兽: // 炎术士 - 火魔兽
            case 机械师.人造卫星: // 机械师 - 人造卫星
            case 机械师.人造卫星2: // 机械师 - 人造卫星
            case 机械师.人造卫星3: // 机械师 - 人造卫星
                return SummonMovementType.FOLLOW;
            default:
                return null;
        }
    }

    public boolean isSkill() {
        return skill;
    }

    public int getSourceId() {
        return sourceid;
    }

    public int getMastery() {
        return mastery;
    }

    public int getRange() {
        return range;
    }

    public int getFixedDamage() {
        return fixDamage;
    }
    
    private int getMaxLevel() {
        return maxLevel;
   }

    public String getBuffString() {
        StringBuilder sb = new StringBuilder();
        sb.append("WATK: ");
        sb.append(this.watk);
        sb.append(", ");
        sb.append("WDEF: ");
        sb.append(this.wdef);
        sb.append(", ");
        sb.append("MATK: ");
        sb.append(this.matk);
        sb.append(", ");
        sb.append("MDEF: ");
        sb.append(this.mdef);
        sb.append(", ");
        sb.append("ACC: ");
        sb.append(this.acc);
        sb.append(", ");
        sb.append("AVOID: ");
        sb.append(this.avoid);
        sb.append(", ");
        sb.append("SPEED: ");
        sb.append(this.speed);
        sb.append(", ");
        sb.append("JUMP: ");
        sb.append(this.jump);
        sb.append(".");

        return sb.toString();
    }

    /**
     * 
     * @return true if the effect should happen based on it's probablity, false otherwise
     */
    public boolean makeChanceResult() {
        return prop == 1.0 || Math.random() < prop;
    }


    public static class CancelEffectAction implements Runnable {

        private MapleStatEffect effect;
        private WeakReference<MapleCharacter> target;
        private long startTime;

        public CancelEffectAction(MapleCharacter target, MapleStatEffect effect, long startTime) {
            this.effect = effect;
            this.target = new WeakReference<MapleCharacter>(target);
            this.startTime = startTime;
        }

        @Override
        public void run() {
            MapleCharacter realTarget = target.get();
            if (realTarget != null) {
                if (realTarget.inCS() || realTarget.inMTS()) {
                    realTarget.addToCancelBuffPackets(effect, startTime);
                    return;
                }
                realTarget.cancelEffect(effect, false, startTime);
            }
        }
    }

   public boolean isTornado() {
     return (this.sourceid == 双刀.龙卷风) || (this.sourceid == 双刀.龙卷风_攻击);
   }
   
    public static MapleStatEffect getInstance() {
        if (instance == null) {
            instance = new MapleStatEffect();
        }
        return instance;
    }
    
    public boolean isLingQi() {
        return skill && (sourceid == 战法.黑暗灵气
                || sourceid == 战法.蓝色灵气
                || sourceid == 战法.黄色灵气
                || sourceid == 战法.进阶黑暗灵气
                || sourceid == 战法.进阶蓝色灵气
                || sourceid == 战法.进阶黄色灵气);
    }
    
    public boolean isSkillBianShen() {
        return skill && (sourceid == 拳手.超人变形 || sourceid == 拳手.超级变身 || sourceid == 风灵使者.信天翁 || sourceid == 奇袭者.超人变形);
    }
    
    public boolean is能量获得() {
        return skill && (sourceid == 拳手.能量获得 || sourceid == 奇袭者.能量获得);
    }
    
    public boolean is骰子(){
        return skill && (sourceid == 枪手.幸运骰子 || sourceid == 拳手.幸运骰子 || sourceid == 机械师.幸运骰子);
    }
    
    public boolean is传送门(){
        return skill && (sourceid == 机械师.传送门_GX_9);
    }
    
    public static int 技能解析(String 技能解析式, int Int型技能等级, int 返回的默认值) {
        int 返回的最终结果;
        String String型技能等级 = String.valueOf(Int型技能等级);
        if (技能解析式 == null)
            返回的最终结果 = 返回的默认值;
        else {
                ScriptEngineManager mgr = new ScriptEngineManager();
                ScriptEngine engine = mgr.getEngineByExtension("js");
                // x u d 处理
                技能解析式 = 技能解析式.replace("x", String型技能等级);
                技能解析式 = 技能解析式.replace("u", "Math.ceil");
                技能解析式 = 技能解析式.replace("d", "Math.floor");
                技能解析式 = 技能解析式.replace("=", ""); //盛大的xml有些加了个"=" 垃圾盛大 
                //System.out.println("替换式："+技能解析式);
                String result = null;
                try {
                    result = engine.eval(技能解析式).toString();
                } catch (ScriptException ex) {
                    System.out.println("技能解析报错："+ex);
                }
                //输出的结果 是xx.0 这样是为了去除小数点以及后面的部分
                String theFinalResult = result.substring(0, result.length() - 2);
                //String theFinalResult = result;
                返回的最终结果 = Integer.valueOf(theFinalResult);
                //System.out.println("结果输出："+theFinalResult);
        }
        return 返回的最终结果;
    }
    
    public double getmHpR() {
        return mhpR;
    }

    public double getmMpR() {
        return mmpR;
    }
    
    public int geteMHp() {
        return emhp;
    }

    public int geteMMp() {
        return emmp;
    }
    
}